package util;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Random;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class DGO extends Configured implements Tool {

	public static final int MILLION = 1024 * 1024;
	public static Path outFile;
	public static int lines;
	public static FileSystem fs;

	public DGO() {
		Configuration conf = new Configuration();

		try {
			fs = FileSystem.get(conf);
		} catch (IOException e) {
			e.printStackTrace();
		}

		lines = 1024;
	}

	public static class Ints {

		public static long genInts(int lines, int fct /* unit k */, Path path)
				throws IOException {
			Random rdm = new Random();
			long outNum = 0;
			if (fs.exists(path)) {
				fs.delete(path, true);
			}
			// FSDataOutputStream out = fs.create(path);
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
					fs.create(path, true)));
			final int lineLen = 1024 * fct;
			for (int i = 0; i < lines; i++) {

				StringBuffer buf = new StringBuffer(1024);
				for (int j = 0; j < lineLen; j++) {
					int n = 1;
					outNum = 1l * i * lineLen + j;
					if (outNum % MILLION == 1)
						n = rdm.nextInt(9999);
					buf.append(n + " ");
				}

				out.write(buf.toString().trim());
				out.newLine();
				if (i % 499 == 1)
					System.out.print(".");
			}

			out.close();
			System.out.println();
			// System.out.println("generate " + (outNum+1) + " int" );
			return outNum + 1;
		}

	}

	public static class RealNum {

		public static long genReals(int lines, int fct /* unit k */, Path path)
				throws IOException {
			Random rdm = new Random();
			long outNum = 0;
			if (fs.exists(path)) {
				fs.delete(path, true);
			}
			// FSDataOutputStream out = fs.create(path);
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
					fs.create(path, true)));
			final int lineLen = 1024 * fct;
			for (int i = 0; i < lines; i++) {

				StringBuffer buf = new StringBuffer(1024);
				for (int j = 0; j < lineLen; j++) {
					float n = 1.0f;
					outNum = 1l * i * lineLen + j;
					if (outNum % MILLION == 1) {
						n = rdm.nextFloat() * 999;
					}
					buf.append(n + " ");
				}

				out.write(buf.toString().trim());
				out.newLine();
				if (i % 499 == 1)
					System.out.print(".");
			}

			out.close();
			System.out.println();
			System.out.println("generate " + (outNum + 1) + " real numbers");
			return outNum + 1;
		}

	}

	public static class Pairs {

		public static long genPairs(int lines, int fct, Path path)
				throws IOException {
			Random rdm = new Random();
			long outNum = 1;
			if (fs.exists(path))
				fs.delete(path, true);
			// FSDataOutputStream out = fs.create(path);
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
					fs.create(path, true)));
			final int lineLen = 1024 * fct;
			for (int i = 0; i < lines; i++) {
				long n = 0;
				StringBuffer buf = new StringBuffer(1024);
				for (int j = 1; j <= lineLen; j++) {
					outNum = 1l * i * lineLen + j;
					n = outNum;
					if (outNum % MILLION == 1)
						n = rdm.nextInt(9999);
					buf.append("(" + outNum + "," + n + ")" + " ");
				}

				// out.writeUTF(buf.toString().trim());
				out.write(buf.toString().trim());
				out.newLine();
				if (i % 499 == 1)
					System.out.print(".");
			}

			System.out.println();
			out.close();
			return outNum;
		}

	}

	public static class Tags {

		public static long genTags(int lines, int fct, Path path)
				throws IOException {
			long outNum = 0;
			// FSDataOutputStream out = fs.create(path);
			if (fs.exists(path))
				fs.delete(path, true);
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
					fs.create(path, true)));
			final int lineLen = 1024 * fct / 2;
			for (int i = 0; i < lines; i++) {

				StringBuffer buf = new StringBuffer(1024);
				for (int j = 1; j <= lineLen; j++) {
					String n = "( ) ";
					outNum = 1l * i * lineLen * 2 + j * 2;
					if (outNum % MILLION == 2)
						n = ") ( ";
					buf.append(n);
				}

				// write a line
				// out.writeUTF(buf.toString().trim());
				out.write(buf.toString().trim());
				out.newLine();
				if (i % 499 == 1)
					System.out.print(".");
			}

			out.close();
			System.out.println();
			return outNum;
		}

	}

	@Override
	public int run(String[] args) throws Exception {

		if (args.length < 3) {
			System.err
					.println("[Type:int|pair|tag] [Length (m)]  [output path] [line-length(K)]");
			System.exit(-1);
		}

		int m = Integer.parseInt(args[1]);
		outFile = new Path(args[2]);
		int div = 1;
		if (args.length > 3) {
			div = Integer.parseInt(args[3]);
			lines = m * 1024 / div;
		} else
			lines = Integer.parseInt(args[1]) * 1024;

		long res = 0;
		switch (args[0]) {
		case "pair":
			res = Pairs.genPairs(lines, div, outFile);
			break;
		case "int":
			res = Ints.genInts(lines, div, outFile);
			break;
		case "tag":
			res = Tags.genTags(lines, div, outFile);
			break;
		case "real":
			res = RealNum.genReals(lines, div, outFile);
			break;
		default:
			System.err
					.println("[Type: int | real | pair | tag] [Length (m)] [output path] [line-lengthb K]");
			System.exit(-1);

		}

		return (int) (res / MILLION);
	}

	public static void main(String[] args) throws Exception {
		int res = ToolRunner.run(new Configuration(), new DGO(), args);
		System.out.println("generate " + res + " M " + args[0]);

		System.exit(res == Integer.parseInt(args[1]) ? 0 : 1);
	}

}
